間違ってmainから派生させたブランチを、git cherry-pickを使ってdevelopからの派生に修正してみた

間違ってmainから派生させたブランチを、git cherry-pickを使ってdevelopからの派生に修正してみた

間違ってdevelopブランチではなくmainブランチからブランチを切ってしまった場合、新しくdevelopからブランチを切ってgit cherry-pickコマンドを使用することで、実質的に派生元ブランチを変更することができます。
Clock Icon2024.10.20

間違ってmainからブランチを切ってしまった

おのやんです。

みなさん、本来はdevelopブランチから機能追加ブランチを作成するべきものを、間違ってmainブランチから機能追加ブランチを作成してコミットを重ねてしまった経験はありませんか?私はあります(懺悔)。

こういった場合、git rebase ontoコマンドを使って派生元ブランチを修正できます。しかし、git rebase ontoはコミットの改変に当たるため、すでにremoteにpushしている場合や複数人で作業している場合はNGとのことです。実際、私が遭遇したケースでも複数コミットを重ねた上で、それらをGitHubにpushしていました。

ただしこの方法は「コミットの改変にあたる」点に注意が必要です。
すでにpush済だったブランチの場合、リモートとローカルの履歴が不整合になるため普通にpushしようとしてもエラーになりす。-fオプションをつけて強制的にpushさせなければなりません。

自分ひとりで作業しているブランチであればこれで全く問題ないのですが、他の人と共同で作業しているブランチで勝手に過去のコミットを改変するのはNG。
方法1を使う際は、この点が確実にクリアできる状況であるときだけにしておきましょう。

https://www.granfairs.com/blog/entry-3219/

ということで、今回はgit rebase ontoではないもうひとつの方法である、git cherry-pickを使って、remoteにpush済みのブランチを修正してみたいと思います。

状況

今回のケースでは、機能追加用ブランチ(feature/xxxx)は原則developブランチから派生させるという規則がありました、そのため、通常であればこちらのようなブランチの管理になるはずでした。

normal_git_branch

しかし、本来developブランチから派生させるはずの機能追加用ブランチを、誤ってmainブランチから派生させてしまいました。この間違ったブランチにはコミットが重なっていて、GitHubにもpushしていました。

mistake_git_branch

ということで、これらの間違ったブランチ・コミットを、develop派生の新しいブランチに修正したいと思います。

解決策

まず、developブランチから修正用の新しい機能追加ブランチを作成します。

git switch -c feature/yyyy

create_new_git_branch

そして、 新しく作成した機能追加用ブランチにいる状態で、git cherry-pick コマンドを実行します。今回は、一度に複数のコミットを新ブランチにコピーしたいため、..でコミットIDをつなげています。このとき、aaaa..ddddのように複数コミットを範囲指定しますが、git cherry-pickの仕様として、コピー対象のコミットのうちaaaaは含めません。またddddは含めます。このため、画像のようなイメージでcherry-pickの範囲を確認するのを強くオススメします。

git cherry-pick aaaa..dddd

git-cherry-pick

こうすることで、先ほど新規作成したブランチに誤ブランチのコミットがコピーされた状態になります。この状態で、git push origin feature/yyyyで新しいブランチをpushしたり、git branch -d feature/xxxxで誤ブランチを削除したりすれば、実質的に派生元ブランチをmainからdevelopに修正できるという寸法です。

delete_git_branch

git cherry-pickは慎重に

git cherry-pickは、カレントブランチに変更を加える作業ですので、gitコマンドの仕様などを確認して、確実に期待した通りの挙動を示すことを確認してから実行するようにしてください。私自身、20分くらいコマンドの挙動の確認に時間をかけました。

Gitブランチの派生元を間違えた場合は、参考にしていただけると幸いです。では!

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.